import { ISmsCaptchaArg, smsSignUp, smsPasswordRetrieve, smsUpdateOrder, smsAuthPass, smsAuthNoPass } from './sms';
import { subscribe } from './bus';
import env from '../config/env';
import { curry, apply, tap, propEq, find, values } from 'ramda';
import { findOne, redis, findAll, trans, findById, create, deleteOne, modifyInstanceProperties, validator } from "./db";
import { User } from '../api/auth/auth.model';
import { unescape } from 'querystring'

const { pipe, lensProp, view, __ } = require('ramda');
const { chain, map, liftA2 } = require('pointfree-fantasy');
const Task = require('data.task');
const Maybe = require('data.maybe');
// generate captcha -> store captcha -> send captcha

const captchaGenerator = {
    fixed: () => '1234',
    random: () => Math.floor(Math.random() * Math.pow(10, 6))
};

const generateCaptcha: () => string = captchaGenerator[env.captcha.factoryName] || captchaGenerator['random'];

const storeCaptcha = curry<string, string, string, any>((prefix: string, principal: string, captcha: string): any => {
    console.log(`Sending captcha code ${principal} ${captcha} ...`);
    return new Task((rej, res) =>
        redis
            .multi()
            .set(`${prefix}-${principal}`, captcha)
            .expire(`${prefix}-${principal}`, env.captcha.ttl)
            .exec((err, result) => {
                if (err) rej(err);
                res({ principal, captcha, prefix });
            })
    );
});

interface ICaptchaArg extends ISmsCaptchaArg {
    prefix?: string;
}

interface ICaptchaHandler {
    (principal: string, prefix?: string): any;
}

const sendNoCaptcha = (fn: (args: | ISmsCaptchaArg) => Promise<any>): ICaptchaHandler => (principal, prefix) => {
    prefix = prefix || 'username';
    return pipe(
        generateCaptcha,
        storeCaptcha(prefix, principal),
        chain(x => new Task((rej, res) => {
            res('send captcha ok');
        })),
        // chain(x => new Task((rej, res) =>
        //     fn(x).then(res).catch(rej)))
    )();
};

const sendCaptcha = (fn: (args: | ISmsCaptchaArg) => Promise<any>): ICaptchaHandler => (principal, prefix) => {
    prefix = prefix || 'username';
    return pipe(
        generateCaptcha,
        storeCaptcha(prefix, principal),
        chain(x => new Task((rej, res) =>
            fn(x).then(res).catch(rej)))
    )();
};


const sendAuthPass = (smsInfo) => {
    return pipe(
        Maybe.fromNullable,
        chain(info => findOne(User, { where: { id: info.profileId } })),
        map(info => smsAuthPass({ principal: info.username }))
    )(smsInfo)
}

const sendAuthNoPass = (smsInfo) => {
    return pipe(
        Maybe.fromNullable,
        chain(info => findOne(User, { where: { id: info.profileId } })),
        // chain(info => new Task((rej, res) => {
        //     Profile.findOne({ where: { id: info.userId } }).then(result => {
        //         let principal = info.username;
        //         let message = info.authRemark;
        //         res({ principal, message })
        //     }).catch(rej)
        // })),
        chain(info => smsAuthNoPass({ principal: info.username, message: smsInfo.authRemark }))
    )(smsInfo)
}

const autoTestCaptcha = ({ principal, captcha, prefix }) => Promise.resolve();

const sendSmsSignUp = sendNoCaptcha(smsSignUp);
const sendSmsPasswordRetrieve = sendCaptcha(smsPasswordRetrieve);
const sendSmsAuthPass = sendAuthPass;
const sendSmsAuthNoPass = sendAuthNoPass;

export {
    sendSmsSignUp,
    sendSmsPasswordRetrieve,
    sendSmsAuthPass,
    sendSmsAuthNoPass
}